package com.github.hwangrq.myrpc.consumer.proxy;

import com.alibaba.fastjson.JSON;
import com.github.hwangrq.myrpc.api.common.RpcRequest;
import com.github.hwangrq.myrpc.api.common.RpcResponse;
import com.github.hwangrq.myrpc.api.zk.ZkConstant;
import com.github.hwangrq.myrpc.consumer.client.RpcClient;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.ZkClient;
import org.springframework.stereotype.Component;

import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Random;
import java.util.UUID;


@Component
@Slf4j
@Data
public class RpcClientProxy {

    private int requestCount = 0;

    public Object createProxy(Class<?> serviceClass) {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{serviceClass},
                (proxy, method, args) -> {
                    //1.封装request请求对象
                    RpcRequest rpcRequest = new RpcRequest();
                    rpcRequest.setRequestId(UUID.randomUUID().toString());
                    rpcRequest.setClassName(serviceClass.getName());
                    rpcRequest.setMethodName(method.getName());
                    rpcRequest.setParameters(args);
                    rpcRequest.setParameterTypes(method.getParameterTypes());
                    //2.创建RpcClient对象
                    RpcClient rpcClient =  new RpcClient();
                    try {
                        //3.发送消息
                        String responseMsg = rpcClient.send(JSON.toJSONString(rpcRequest)).toString();
                        RpcResponse rpcResponse = JSON.parseObject(responseMsg, RpcResponse.class);
                        if (rpcResponse.getError() != null) {
                            throw new RuntimeException(rpcResponse.getError());
                        }
                        //4.返回结果
                        Object result = rpcResponse.getResult();
                        System.out.println("当前RPC-Client【{}:{}】结果为：{}"+ rpcClient.getIp()+":"+rpcClient.getPort()+":"+result.toString()) ;
                        return JSON.parseObject(result.toString(), method.getReturnType());
                    } catch (Exception e){
                        System.out.println(e.getMessage());
                        throw e;
                    }
                });
    }


//    private RpcClient getRpcClient() throws Exception {
//        ZkClient zkClient = new ZkClient(ZkConstant.DEFAULT_SERVER);
//        List<String> serverList =  zkClient.getChildren(ZkConstant.NAMESPACE);
//
//        int chooseTime = Integer.MAX_VALUE;
//        String ip = null;
//        int port = 0;
//        for (String server : serverList) {
//            Object timeObj = zkClient.readData(ZkConstant.NAMESPACE + "/" + server);
//            if (timeObj == null) {
//                continue;
//            }
//            int time = Integer.parseInt(timeObj.toString());
//            if(time < chooseTime) {
//                chooseTime = time;
//                ip = server.split(":")[0];
//                port = Integer.parseInt(server.split(":")[1]);
//            }
//        }
//        //如果ZK服务器上还未保存服务端的响应时间信息，则随机选择一台服务端进行绑定
//        if(chooseTime == 0 || ip == null) {
//            //随机选择一台服务器进行绑定
//            int i = new Random().nextInt(serverList.size());
//            String randomServerStr = serverList.get(i);
//            ip = randomServerStr.split(":")[0];
//            port = Integer.parseInt(randomServerStr.split(":")[1]);
//        }
//
//        //注册该节点监听，如果下面的子节点列表发生变化，则重新进行服务端连接
//        zkClient.subscribeChildChanges(ZkConstant.NAMESPACE, new IZkChildListener() {
//            @Override
//            public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
//                log.info("检测到有子节点发生改变，重新获取子节点列表");
//                getRpcClient();
//            }
//        });
//        return new RpcClient(ip, port);
//    }
}
